package com.example.filesftp.ftptransfer.util;

import com.example.common.core.util.R;
import com.example.filesftp.ftptransfer.domain.entity.FileTransferConfig;
import com.mchange.v2.lang.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Stream;

@Slf4j
@Component
public class FtpUtil {
    // 设置FTP服务器字符编码（解决中文乱码问题）
    private static final String GBK_ENCODING = "GBK"; // 或使用"UTF-8"，根据服务器实际情况调整
    private static final String UTF_8_ENCODING = "UTF-8";
    /**
     * FTP下载文件
     * @param config 文件传输配置
     * @param date 日期参数
     * @return 操作结果
     * @throws IOException IO异常
     */
//    public R ftpDownloadFile(FileTransferConfig config, LocalDate date) throws IOException {
//        // 将日期转换为第二天0点的起报时间
//        LocalDateTime publishTime = date.plusDays(1).atStartOfDay();
//        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHH");
//        String publishTimeStr = publishTime.format(formatter);
//
//
//        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
//        String createTimeStr = date.format(dateTimeFormatter);
//        // CSV文件名
//        String csvFileName = config.getCsvFileName();
//        // 指定文件名
//        String designateFileName = config.getFileName();
//
//        String dynamicPattern = null;
//        Pattern filePattern = null;
//        // 指定文件下载模式
//        if (StringUtils.nonEmptyString(designateFileName)) {
//            dynamicPattern = designateFileName;
//            filePattern = Pattern.compile(dynamicPattern);
//        }
//        // CSV文件下载模式
//        if (StringUtils.nonEmptyString(csvFileName)) {
//            dynamicPattern = csvFileName
//                    .replace("(?<time>\\d{8})", createTimeStr)
//                    .replace("(?<date>\\d{10})", publishTimeStr);
//            filePattern = Pattern.compile(dynamicPattern);
//        }
//
//        // 确定操作系统类型
//        boolean isRemoteWindows = "1".equals(config.getRemoteType());
//        boolean isLocalWindows = "1".equals(config.getLocalType());
//
//        // 处理路径格式
//        String remotePath = PathUtils.toRemotePath(config.getRemotePath(), isRemoteWindows);
//        String localPath = PathUtils.toLocalPath(config.getLocalPath(), isLocalWindows);
//
//        // 检查并创建本地目录
//        Path localDirPath = Paths.get(localPath);
//        if (!Files.exists(localDirPath)) {
//            try {
//                Files.createDirectories(localDirPath);
//            } catch (IOException e) {
//                log.error("创建本地目录失败: {}", localDirPath, e);
//                return R.failed("创建本地目录失败");
//            }
//        }
//
//        // 检查本地目录下是否已存在匹配文件
//        boolean isFileExists = false;
//        List<File> allFile = new ArrayList<>();
//        try (Stream<Path> pathStream = Files.list(localDirPath)) {
//            pathStream.forEach(path -> allFile.add(path.toFile()));
//            if (filePattern != null) {
//                Pattern finalFilePattern = filePattern;
//                isFileExists = allFile.stream().anyMatch(file -> finalFilePattern.matcher(file.getName()).matches());
//            }
//        } catch (IOException e) {
//            log.error("目录遍历失败: {}", localDirPath, e);
//            return R.failed("目录遍历失败");
//        }
//
//        if (isFileExists) {
//            log.info("已存在匹配文件，跳过下载，目录: {}", localDirPath);
//        }
//
//        FTPClient ftpClient = null;
//        try {
//            // 初始化FTP客户端
//            ftpClient = new FTPClient();
//            // 连接FTP服务器
//            ftpClient.connect(config.getHost(), config.getPort());
//            // 登录FTP服务器
//            if (!ftpClient.login(config.getUsername(), config.getPassword())) {
//                return R.failed("FTP登录失败");
//            }
//
//            // 设置传输模式
//            ftpClient.enterLocalPassiveMode();
//            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
//            String serverType = ftpClient.getSystemType();
//            log.info("FTP服务器类型: {}", serverType);
//            String remoteEncodeType = null;
//            String localEncodeType =System.getProperty("sun.jnu.encoding");
//            // 针对不同服务器类型调整编码（Windows通常使用GBK，Linux/Unix使用UTF-8）
//            if (serverType.toUpperCase().contains("WINDOWS")) {
//                ftpClient.setControlEncoding(GBK_ENCODING);
//                remoteEncodeType = GBK_ENCODING;
//            } else {
//                ftpClient.setControlEncoding(UTF_8_ENCODING);
//                remoteEncodeType = UTF_8_ENCODING;
//            } // 处理远程路径编码
//            String encodedRemotePath = new String(remotePath.getBytes(remoteEncodeType), localEncodeType);
//            // 检查远程路径是文件还是目录
//            if (isRemoteFile(ftpClient, encodedRemotePath)) {
//                // 下载单个文件
//                downloadSingleFile(ftpClient, encodedRemotePath, localDirPath,remoteEncodeType,localEncodeType);
//            } else {
//                // 下载整个目录
//                downloadDirectory(ftpClient, encodedRemotePath, localDirPath,remoteEncodeType,localEncodeType);
//            }
//        } catch (Exception ex) {
//            log.error(ex.getLocalizedMessage(), ex);
//            return R.failed("FTP操作失败: " + ex.getMessage());
//        } finally {
//            // 关闭FTP连接
//            try {
//                if (ftpClient != null && ftpClient.isConnected()) {
//                    ftpClient.logout();
//                    ftpClient.disconnect();
//                }
//            } catch (Exception e) {
//                log.error(e.getLocalizedMessage(), e);
//            }
//        }
//        return R.ok("执行成功");
//    }

    /**
     * FTP下载文件
     * @param config 文件传输配置
     * @param date 日期参数
     * @return 操作结果
     * @throws IOException IO异常
     */
    public R ftpDownloadFile(FileTransferConfig config, LocalDate date) throws IOException {
        // 将日期转换为第二天0点的起报时间
        LocalDateTime publishTime = date.plusDays(1).atStartOfDay();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHH");
        String publishTimeStr = publishTime.format(formatter);

        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String createTimeStr = date.format(dateTimeFormatter);
        // CSV文件名
        String csvFileName = config.getCsvFileName();
        // 指定文件名
        String designateFileName = config.getFileName();

        String dynamicPattern = null;
        Pattern filePattern = null;
        // 指定文件下载模式
        if (StringUtils.nonEmptyString(designateFileName)) {
            dynamicPattern = designateFileName;
            filePattern = Pattern.compile(dynamicPattern);
        }
        // CSV文件下载模式
        if (StringUtils.nonEmptyString(csvFileName)) {
            dynamicPattern = csvFileName
                    .replace("(?<time>\\d{8})", createTimeStr)
                    .replace("(?<date>\\d{10})", publishTimeStr);
            filePattern = Pattern.compile(dynamicPattern);
        }

        // 确定操作系统类型
        boolean isRemoteWindows = "1".equals(config.getRemoteType());
        boolean isLocalWindows = "1".equals(config.getLocalType());

        // 处理路径格式
        String remotePath = PathUtils.toRemotePath(config.getRemotePath(), isRemoteWindows);
        String localPath = PathUtils.toLocalPath(config.getLocalPath(), isLocalWindows);

        // 检查并创建本地目录
        Path localDirPath = Paths.get(localPath);
        if (!Files.exists(localDirPath)) {
            try {
                Files.createDirectories(localDirPath);
            } catch (IOException e) {
                log.error("创建本地目录失败: {}", localDirPath, e);
                return R.failed("创建本地目录失败");
            }
        }

        FTPClient ftpClient = null;
        try {
            // 初始化FTP客户端
            ftpClient = new FTPClient();
            // 连接FTP服务器
            ftpClient.connect(config.getHost(), config.getPort());
            // 登录FTP服务器
            if (!ftpClient.login(config.getUsername(), config.getPassword())) {
                return R.failed("FTP登录失败");
            }

            // 设置传输模式
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            String serverType = ftpClient.getSystemType();
            log.info("FTP服务器类型: {}", serverType);
            String remoteEncodeType = null;
            String localEncodeType = System.getProperty("sun.jnu.encoding");
            // 针对不同服务器类型调整编码（Windows通常使用GBK，Linux/Unix使用UTF-8）
            if (serverType.toUpperCase().contains("WINDOWS")) {
                ftpClient.setControlEncoding(GBK_ENCODING);
                remoteEncodeType = GBK_ENCODING;
            } else {
                ftpClient.setControlEncoding(UTF_8_ENCODING);
                remoteEncodeType = UTF_8_ENCODING;
            }
            // 处理远程路径编码
            String encodedRemotePath = new String(remotePath.getBytes(remoteEncodeType), localEncodeType);
            if (StringUtils.nonEmptyString(dynamicPattern)) {
                encodedRemotePath = encodedRemotePath+dynamicPattern;
            }
            // 检查远程路径是文件还是目录
            if (isRemoteFile(ftpClient, encodedRemotePath)) {
                // 下载单个文件（增加查重逻辑）
                if (!shouldSkipDownload(ftpClient, encodedRemotePath, localDirPath, remoteEncodeType, localEncodeType)) {
                    downloadSingleFile(ftpClient, encodedRemotePath, localDirPath, remoteEncodeType, localEncodeType);
                } else {
                    log.info("文件已存在且相同，跳过下载: {}", encodedRemotePath);
                }
            } else {
                // 下载整个目录（增加查重逻辑）
                downloadDirectoryWithCheck(ftpClient, encodedRemotePath, localDirPath, remoteEncodeType, localEncodeType);
            }
        } catch (Exception ex) {
            log.error(ex.getLocalizedMessage(), ex);
            return R.failed("FTP操作失败: " + ex.getMessage());
        } finally {
            // 关闭FTP连接
            try {
                if (ftpClient != null && ftpClient.isConnected()) {
                    ftpClient.logout();
                    ftpClient.disconnect();
                }
            } catch (Exception e) {
                log.error(e.getLocalizedMessage(), e);
            }
        }
        return R.ok("执行成功");
    }

    /**
     * FTP上传文件
     * @param config 文件传输配置
     * @param date 日期参数
     * @return 操作结果
     * @throws IOException IO异常
     */
    public R ftpUploadFile(FileTransferConfig config, LocalDate date) throws IOException {
        // 将日期转换为第二天0点的起报时间
        LocalDateTime publishTime = date.plusDays(1).atStartOfDay();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHH");
        String publishTimeStr = publishTime.format(formatter);

        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String createTimeStr = date.format(dateTimeFormatter);
        // CSV文件名
        String csvFileName = config.getCsvFileName();
        // 指定文件名
        String designateFileName = config.getFileName();

        boolean isRemoteWindows = "1".equals(config.getRemoteType());
        boolean isLocalWindows = "1".equals(config.getLocalType());

        FTPClient ftpClient = null;
        try {
            // 初始化FTP客户端
            ftpClient = new FTPClient();
            // 连接FTP服务器
            ftpClient.connect(config.getHost(), config.getPort());
            // 登录FTP服务器
            if (!ftpClient.login(config.getUsername(), config.getPassword())) {
                return R.failed("FTP登录失败");
            }
            // 解决中文文件名乱码的关键设置
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            ftpClient.enterLocalPassiveMode();

            // 获取FTP服务器系统类型，调整编码设置
            String serverType = ftpClient.getSystemType();
            log.info("FTP服务器类型: {}", serverType);
            String remoteEncodeType = null;
            String localEncodeType = System.getProperty("sun.jnu.encoding");
            // 针对不同服务器类型调整编码
            if (serverType.toUpperCase().contains("WINDOWS")) {
                ftpClient.setControlEncoding(GBK_ENCODING);
                remoteEncodeType = GBK_ENCODING;

            } else {
                ftpClient.setControlEncoding(UTF_8_ENCODING);
                remoteEncodeType = UTF_8_ENCODING;
            }

            // 设置传输模式
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

            // 处理本地路径
            String localPath = PathUtils.toLocalPath(config.getLocalPath(), isLocalWindows);
            String remoteBaseDir = config.getRemotePath();

//            // Windows系统路径验证
//            if ("1".equals(config.getRemoteType())) {
//                if (!remoteBaseDir.matches("^[A-Za-z]:\\\\.*")) {
//                    log.error("Windows系统必须指定驱动器字母路径，如F:\\path\\to\\dir");
//                    return R.failed("无效的Windows路径格式");
//                }
//                remoteBaseDir = PathUtils.toWindowsRemotePath(remoteBaseDir);
//                log.debug("转换后的远程路径: {}", remoteBaseDir);
//            }

            // 创建远程目录
            createRemoteDir(ftpClient, remoteBaseDir, isRemoteWindows);

            // 构建完整本地路径
            if (StringUtils.nonEmptyString(designateFileName)) {
                localPath = localPath + File.separator + designateFileName;
            } else if (StringUtils.nonEmptyString(csvFileName)) {
                localPath = localPath + File.separator +
                        csvFileName.replace("${publishTime}", publishTimeStr)
                                .replace("${createTime}", createTimeStr);
            }

            File localFile = new File(localPath);
            if (localFile.isFile()) {
                // 上传单个文件（处理文件名编码）
                String encodedRemoteDir = new String(remoteBaseDir.getBytes(localEncodeType), remoteEncodeType);
                String encodedFileName = new String(localFile.getName().getBytes(localEncodeType), remoteEncodeType);
                // 上传单个文件
                uploadFile(ftpClient, encodedRemoteDir, localFile, encodedFileName,remoteEncodeType,localEncodeType);
            } else if (localFile.isDirectory()) {
                // 上传整个目录（处理文件名编码）
                String encodedRemoteDir = new String(remoteBaseDir.getBytes(localEncodeType), remoteEncodeType);
                // 上传整个目录
                uploadDirectory(ftpClient, encodedRemoteDir, localFile, isRemoteWindows,remoteEncodeType,localEncodeType);
            } else {
                log.error("本地路径既不是文件也不是目录: {}", localPath);
                return R.failed("无效的本地路径");
            }
        } catch (Exception e) {
            log.error("FTP操作出错: " + e.getMessage(), e);
            return R.failed("FTP操作失败");
        } finally {
            // 关闭FTP连接
            try {
                if (ftpClient != null && ftpClient.isConnected()) {
                    ftpClient.logout();
                    ftpClient.disconnect();
                }
            } catch (IOException e) {
                log.error(e.getLocalizedMessage(), e);
            }
        }
        return R.ok("执行成功");
    }

    /**
     * 递归创建远程目录
     * @param ftpClient FTP客户端
     * @param remoteDir 远程目录路径
     * @param isRemoteWindows 是否Windows系统
     * @throws IOException IO异常
     */
    private static void createRemoteDir(FTPClient ftpClient, String remoteDir, boolean isRemoteWindows)
            throws IOException {
        String[] folders = remoteDir.split( "/");
        StringBuilder pathBuilder = new StringBuilder();

        // 对于绝对路径，以/开头
        if (remoteDir.startsWith("/")) {
            pathBuilder.append("/");
        }

        for (String folder : folders) {
            if (folder.isEmpty()) {
                continue;
            }
            pathBuilder.append("/").append(folder);
            String currentPath = pathBuilder.toString();

            try {

                if (!ftpClient.changeWorkingDirectory(currentPath)) {
                    if (!ftpClient.makeDirectory(currentPath)) {
                        throw new IOException("创建目录失败: " + currentPath +
                                "，服务器返回: " + ftpClient.getReplyString());
                    }
                    log.info("创建远程目录: {}", currentPath);
                }
            } catch (IOException e) {
                log.error("目录操作失败: {}", currentPath, e);
                throw e;
            }
        }
    }

    /**
     * 上传单个文件（解决中文乱码）
     * @param ftpClient FTP客户端
     * @param remoteDir 远程目录
     * @param localFile 本地文件
     * @throws IOException IO异常
     */
    private static void uploadFile(FTPClient ftpClient, String remoteDir, File localFile, String encodedFileName,
                                   String remoteEncodeType, String localEncodeType)
            throws IOException {
        String remoteFilePath = remoteDir + "/" + encodedFileName;

        // 检查远程文件是否存在（处理文件名编码）
        FTPFile[] remoteFiles = ftpClient.listFiles(remoteFilePath);
        if (remoteFiles.length > 0) {
            FTPFile remoteFile = remoteFiles[0];
            long localFileModifiedTime = localFile.lastModified();
            long remoteFileModifiedTime = remoteFile.getTimestamp().getTimeInMillis();

            if (localFileModifiedTime <= remoteFileModifiedTime) {
                String correctFileName = new String(encodedFileName.getBytes(localEncodeType), remoteEncodeType);
                log.info("文件已存在或未修改，跳过上传: {}", correctFileName);
                return;
            }
        }

        // 上传文件
        String correctFileName = new String(encodedFileName.getBytes(localEncodeType), remoteEncodeType);
        log.info("上传文件: {} -> {}", localFile.getPath(), correctFileName);
        try (InputStream fis = new FileInputStream(localFile)) {
            if (!ftpClient.storeFile(remoteFilePath, fis)) {
                throw new IOException("文件上传失败: " + ftpClient.getReplyString());
            }
        }
    }

    /**
     * 递归上传目录（解决中文乱码）
     */
    private static void uploadDirectory(FTPClient ftpClient, String remoteBaseDir,
                                        File localDir, boolean isRemoteWindows,String remoteEncodeType,String localEncodeType) throws IOException {
        Stack<File> dirStack = new Stack<>();
        Stack<String> remoteDirStack = new Stack<>();

        dirStack.push(localDir);
        remoteDirStack.push(remoteBaseDir);

        while (!dirStack.isEmpty()) {
            File currentLocalDir = dirStack.pop();
            String currentRemoteDir = remoteDirStack.pop();

            // 创建远程目录（已处理编码）
            createRemoteDir(ftpClient, currentRemoteDir, isRemoteWindows);

            String correctRemoteDir = new String(currentRemoteDir.getBytes(localEncodeType), remoteEncodeType);
            log.info("处理目录: {} → {}", currentLocalDir.getPath(), correctRemoteDir);

            File[] localFiles = currentLocalDir.listFiles();
            if (localFiles == null) {
                continue;
            }

            for (File file : localFiles) {
                // 处理文件名编码
                String encodedFileName = new String(file.getName().getBytes(localEncodeType), remoteEncodeType);
                String remoteFilePath = currentRemoteDir  +"/"+ encodedFileName;

                if (file.isDirectory()) {
                    dirStack.push(file);
                    remoteDirStack.push(remoteFilePath);
                } else {
                    uploadFile(ftpClient, currentRemoteDir, file, encodedFileName, remoteEncodeType, localEncodeType);
                }
            }
        }
    }

    /**
     * 计算远程目录大小
     * @param ftpClient FTP客户端
     * @param remotePath 远程路径
     * @return 目录大小(字节)
     * @throws IOException IO异常
     */
    private static long getFolderSize(FTPClient ftpClient, String remotePath) throws IOException {
        long size = 0;
        FTPFile[] files = ftpClient.listFiles(remotePath);

        for (FTPFile file : files) {
            if (file.isDirectory()) {
                // 跳过当前目录和上级目录
                if (!file.getName().equals(".") && !file.getName().equals("..")) {
                    // 递归计算子目录大小
                    size += getFolderSize(ftpClient, remotePath + "/" + file.getName());
                }
            } else {
                size += file.getSize();
            }
        }
        return size;
    }


    /**
     * 判断远程路径是否是文件
     * @param ftpClient FTP客户端
     * @param remotePath 远程路径
     * @return true如果是文件，false如果是目录
     * @throws IOException IO异常
     */
    private boolean isRemoteFile(FTPClient ftpClient, String remotePath) throws IOException {
        // 保存当前工作目录
        String originalWorkingDir = ftpClient.printWorkingDirectory();

        try {
            // 方法1：尝试切换目录，如果能切换则是目录
            if (ftpClient.changeWorkingDirectory(remotePath)) {
                // 切换回原目录
                ftpClient.changeWorkingDirectory(originalWorkingDir);
                return false;
            }

            // 方法2：检查文件列表
            FTPFile[] files = ftpClient.listFiles(remotePath);

            // 情况1：路径不存在
            if (files.length == 0) {
                throw new FileNotFoundException("远程路径不存在: " + remotePath);
            }

            // 情况2：明确匹配到一个文件
            if (files.length == 1) {
                String listedName = files[0].getName();
                String pathName = new File(remotePath).getName();

                // 比较文件名（考虑大小写敏感性）
                if (listedName.equals(pathName) ||
                        files[0].getName().equalsIgnoreCase(pathName)) {
                    return !files[0].isDirectory();
                }
            }

            // 方法3：尝试获取文件大小（目录通常返回-1）
            try {
                // 对于文件，这将返回实际大小或0
                // 对于目录，大多数FTP服务器会返回-1或抛出异常
                if (ftpClient.listFiles(remotePath + "/").length > 0) {
                    return false;
                }

                // 尝试获取文件大小
                InputStream is = ftpClient.retrieveFileStream(remotePath);
                if (is != null) {
                    is.close();
                    // 必须调用completePendingCommand来重置连接状态
                    if (!ftpClient.completePendingCommand()) {
                        throw new IOException("无法完成待处理命令");
                    }
                    return true;
                }
            } catch (IOException e) {
                // 获取文件流失败，可能是目录
                return false;
            }

            // 默认情况下认为是文件
            return true;
        } finally {
            // 确保总是恢复到原始工作目录
            if (originalWorkingDir != null) {
                try {
                    ftpClient.changeWorkingDirectory(originalWorkingDir);
                } catch (IOException e) {
                    log.error("无法恢复工作目录: {}", originalWorkingDir, e);
                }
            }
        }
    }
    /**
     * 下载单个文件
     */
    private void downloadSingleFile(FTPClient ftpClient, String remoteFilePath, Path localDirPath,
                                    String remoteEncoding,String localEncoding)
            throws IOException {
        // 获取文件名（从路径中提取）
        String fileName = new File(remoteFilePath).getName();
        String correctFileName = new String(fileName.getBytes(remoteEncoding), localEncoding);

        Path localFilePath = localDirPath.resolve(correctFileName);
        log.info("开始下载文件: {} → {}", remoteFilePath, localFilePath);

        try (OutputStream outputStream = new FileOutputStream(localFilePath.toFile())) {
            if (!ftpClient.retrieveFile(remoteFilePath, outputStream)) {
                throw new IOException("文件下载失败: " + ftpClient.getReplyString());
            }
            log.info("文件下载成功: {}", correctFileName);
        }
    }

    /**
     * 递归下载目录（修复目录下载问题）
     */
//    private void downloadDirectory(FTPClient ftpClient, String remoteDirPath, Path localDirPath,String remoteEncoding,String localEncoding)
//            throws IOException {
//        // 创建本地目录
//        if (!Files.exists(localDirPath)) {
//            Files.createDirectories(localDirPath);
//        }
//
//        // 获取远程目录下的文件和子目录
//        FTPFile[] remoteFiles = ftpClient.listFiles(remoteDirPath);
//
//        for (FTPFile remoteFile : remoteFiles) {
//            // 跳过当前目录和上级目录
//            if (remoteFile.getName().equals(".") || remoteFile.getName().equals("..")) {
//                continue;
//            }
//
//            // 处理文件名编码
//            String correctFileName = new String(remoteFile.getName().getBytes(remoteEncoding), localEncoding);
//            String childRemotePath = remoteDirPath + "/" + remoteFile.getName();
//            Path childLocalPath = localDirPath.resolve(correctFileName);
//
//            if (remoteFile.isDirectory()) {
//                // 递归下载子目录
//                log.info("下载子目录: {}", correctFileName);
//                downloadDirectory(ftpClient, childRemotePath, childLocalPath, remoteEncoding,localEncoding);
//            } else {
//                // 下载文件
//                log.info("下载文件: {}", correctFileName);
//                try (OutputStream outputStream = new FileOutputStream(childLocalPath.toFile())) {
//                    if (!ftpClient.retrieveFile(childRemotePath, outputStream)) {
//                        log.error("文件下载失败: {}", correctFileName);
//                    }
//                }
//            }
//        }
//    }

    /**
     * 检查是否应该跳过下载（文件查重）
     * @param ftpClient FTP客户端
     * @param remoteFilePath 远程文件路径
     * @param localDirPath 本地目录路径
     * @param remoteEncoding 远程编码
     * @param localEncoding 本地编码
     * @return true如果应该跳过下载，false否则
     * @throws IOException IO异常
     */
    private boolean shouldSkipDownload(FTPClient ftpClient, String remoteFilePath, Path localDirPath,
                                       String remoteEncoding, String localEncoding) throws IOException {
        // 获取远程文件信息
        FTPFile[] remoteFiles = ftpClient.listFiles(remoteFilePath);
        if (remoteFiles.length == 0) {
            return false;
        }

        FTPFile remoteFile = remoteFiles[0];
        String fileName = new File(remoteFilePath).getName();
        String correctFileName = new String(fileName.getBytes(remoteEncoding), localEncoding);
        Path localFilePath = localDirPath.resolve(correctFileName);

        // 检查本地文件是否存在
        if (!Files.exists(localFilePath)) {
            return false;
        }

        // 获取本地文件属性
        BasicFileAttributes localAttrs = Files.readAttributes(localFilePath, BasicFileAttributes.class);

        // 比较文件大小
        if (localAttrs.size() != remoteFile.getSize()) {
            return false;
        }

        // 比较修改时间（允许1秒误差）
        long localModified = localAttrs.lastModifiedTime().toMillis();
        long remoteModified = remoteFile.getTimestamp().getTimeInMillis();
        if (Math.abs(localModified - remoteModified) > 1000) {
            return false;
        }

        // 所有条件都满足，可以跳过下载
        return true;
    }

    /**
     * 递归下载目录并检查文件是否已存在（增强版）
     */
    private void downloadDirectoryWithCheck(FTPClient ftpClient, String remoteDirPath, Path localDirPath,
                                            String remoteEncoding, String localEncoding) throws IOException {
        // 创建本地目录
        if (!Files.exists(localDirPath)) {
            Files.createDirectories(localDirPath);
        }

        // 获取远程目录下的文件和子目录
        FTPFile[] remoteFiles = ftpClient.listFiles(remoteDirPath);

        for (FTPFile remoteFile : remoteFiles) {
            // 跳过当前目录和上级目录
            if (remoteFile.getName().equals(".") || remoteFile.getName().equals("..")) {
                continue;
            }

            // 处理文件名编码
            String correctFileName = new String(remoteFile.getName().getBytes(remoteEncoding), localEncoding);
            String childRemotePath = remoteDirPath + "/" + remoteFile.getName();
            Path childLocalPath = localDirPath.resolve(correctFileName);

            if (remoteFile.isDirectory()) {
                // 递归下载子目录
                log.info("处理子目录: {}", correctFileName);
                downloadDirectoryWithCheck(ftpClient, childRemotePath, childLocalPath, remoteEncoding, localEncoding);
            } else {
                // 检查是否需要下载文件
                if (!shouldSkipDownload(ftpClient, childRemotePath, localDirPath, remoteEncoding, localEncoding)) {
                    log.info("下载文件: {}", correctFileName);
                    try (OutputStream outputStream = new FileOutputStream(childLocalPath.toFile())) {
                        if (!ftpClient.retrieveFile(childRemotePath, outputStream)) {
                            log.error("文件下载失败: {}", correctFileName);
                        }
                    }
                } else {
                    log.info("文件已存在且相同，跳过下载: {}", correctFileName);
                }
            }
        }
    }

}